#pragma once
#ifndef _WIN32_WINNT
// default to Vista
#define _WIN32_WINNT 0x0600
#endif

#if _WIN32_WINNT  < 0x0500
#error "_WIN32_WINNT" macro must be set to value greather or equal to 0x0500
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#ifndef _WINDOWS_
#include <windows.h>
#endif

#ifndef _HAS_EXCEPTIONS
# ifdef _CPPUNWIND
#  define _HAS_EXCEPTIONS 1
# else
#  define _HAS_EXCEPTIONS 0
# endif
#endif

#include <yvals.h>
#include <crtdbg.h>
#include <stdexcept>

#define FASTCALL    __fastcall
#define INLINE      __inline
#define FORCEINLINE __forceinline

#define _TR1    _STD tr1::

#define _MAKEWIDESTR( str ) L ## str
#define MAKEWIDESTR( str ) _MAKEWIDESTR( str )

#ifndef ASSUME
# define ASSUME(expr) do { _ASSERT(expr); __analysis_assume(!!(expr)); } while(0)
#endif

#ifndef VERIFY
# ifdef _DEBUG
#  define VERIFY(expr) _ASSERT(expr)
# else
#  define VERIFY(expr) (expr)
# endif // DEBUG
#endif // VERIFY

#ifndef ENSURE
#define ENSURE(expr)        \
do {      \
	int __condVal=!!(expr); \
    _ASSERT_EXPR(__condVal, MAKEWIDESTR(#expr));  \
    if (!__condVal) \
        _RAISE(new _XSTD exception(#expr)); \
} while (0)
#endif // ENSURE

#ifndef ENSURE_RETURN_VAL
#define ENSURE_RETURN_VAL(expr, val) \
do { \
	int __condVal=!!(expr); \
    _ASSERT_EXPR(__condVal, MAKEWIDESTR(#expr));  \
	if(!(__condVal))    \
        return val;     \
} while (0) 

#endif // ENSURE_RETURN_VAL

#define ADDRESS_OF(x)   ((LONG_PTR)(const void*)&x)
#define BOUNDARY_MASK(x)    (sizeof(x)-1)
#define PROPERLY_ALIGNED(x) ((ADDRESS_OF(x) & BOUNDARY_MASK(x)) == 0)

#if (_MSC_VER >= 1400) && (_MSC_VER < 1500) // Visual Studio 2005, MSVC++ 8.0
	#define VS_VERSION 2005
	#define VC_VERSION 80
#elif (_MSC_VER >= 1500) && (_MSC_VER < 1600) // Visual Studio 2008, MSVC++ 9.0
	#define VS_VERSION 2008
	#define VC_VERSION 90
#elif (_MSC_VER >= 1600) && (_MSC_VER < 1700) // Visual Studio 2010, MSVC++ 10.0
	#define VS_VERSION 2010
	#define VC_VERSION 100
#elif (_MSC_VER >= 1700) && (_MSC_VER < 1800) // Visual Studio 2011, MSVC++ 11.0
	#define VS_VERSION 2011
	#define VC_VERSION 110
#endif
#ifndef _NOEXCEPT
#define _NOEXCEPT throw()
#endif
template<typename _Ty>
struct _Safe_bool_
{
    int _Member;
};

#define TYPEDEF_SAFE_BOOL_(type_name)  typedef int _Safe_bool_<type_name>::* _Bool_type   
#define TYPEDEF_SAFE_BOOL   TYPEDEF_SAFE_BOOL_(_Myt);

#define SAFE_TRUE_(type_name)   (&::_Safe_bool_<type_name>::_Member)
#define SAFE_TRUE   SAFE_TRUE_(_Myt)

#define IMPLEMENT_SAFE_BOOL_OPERATOR_(condition, type_name)\
    TYPEDEF_SAFE_BOOL_(type_name);\
    INLINE operator _Bool_type() const throw() { return (condition)? SAFE_TRUE_(type_name) : 0; }
#define IMPLEMENT_SAFE_BOOL_OPERATOR(condition) IMPLEMENT_SAFE_BOOL_OPERATOR_(condition, _Myt)

// HELPER CLASS _If
// Classic metaprogramming _If statement
template <bool _Cond, class _Ty1, class _Ty2>
class _IF
{
public:
	typedef _Ty2 type;
};

template <class _Ty1, class _Ty2>
class _IF<true, _Ty1, _Ty2>
{
public:
	typedef _Ty1 type;
};

#include <intrin.h>

#if VS_VERSION >= 2010
#pragma intrinsic(_ReturnAddress)
#else
#define _ReturnAddress  __impl_ReturnAddress
#endif

#if VS_VERSION < 2010
__declspec(naked) 
static const void* __stdcall __impl_ReturnAddress(void)
{
    __asm {
        push    ebp  
        mov     ebp,esp 
        mov     eax,dword ptr [ebp+4] 
        pop     ebp  
        ret              
    };
}
#endif

// Some useful inlines
class   Inl
{
public:
public:
    // returns true when p is address within stack segment
    // useful to detect that the variable is allocated on stack
    static __forceinline
    bool FASTCALL __impl_is_on_stack(const void* p)
    {
        const PNT_TIB tib((const PNT_TIB)::NtCurrentTeb());
        if (p > tib->StackBase)
            return false;
        return p > tib->StackLimit; 
    }

    __declspec(noinline) 
    static const void*  __stdcall getEIP(void)
    {
        return _ReturnAddress();
    }

    class   _bad_alloc : public _STD exception
    {
    public:
        _bad_alloc(const char* _Message)
            : exception(_Message)
        {}
    };

    static inline void _Xran()
    {
        _THROW(_STD out_of_range, "argument out of range");
    }
    static inline void _Xalloc()
    {
        _THROW(_bad_alloc, "bad allocation");
    }
    static inline void _Xinvarg()
    {
        _THROW(_STD invalid_argument, "invalid argument");
    }
    static inline void _Xnull_ptr()
    {
        _THROW(_STD runtime_error, "null pointer dereference.");
    }
};

#define __is_on_stack    ::Inl::__impl_is_on_stack

template <typename T>
static FORCEINLINE bool ToBool(T i) throw()
{
    return (i != T(0))? true : false;
}


